package com.example.demo1.util;

import com.google.api.client.http.*;
import com.google.api.client.http.apache.ApacheHttpTransport;
import com.google.api.client.util.BackOff;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.conn.ProxySelectorRoutePlanner;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;

import javax.annotation.PreDestroy;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProxySelector;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zhangzichang
 * @Description: TODO
 * @company：CTTIC
 * @since 2021/7/15 13:10
 */
@Slf4j
public class HttpClientWebServiceUtils {
	private static HttpRequestFactory requestFactory;
	private static HttpTransport httpTransport;
	private static final String CONTENT_TYPE_JSON = "application/soap+xml; charset=utf-8";

	private static final int CACHE_SIZE = 4096;


	static {

		HttpParams params = new BasicHttpParams();
		HttpConnectionParams.setStaleCheckingEnabled(params, false);
		HttpConnectionParams.setSocketBufferSize(params, 245760); // 8k(8192) * 30
		ConnManagerParams.setMaxTotalConnections(params, 400);
		ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(200));

		SchemeRegistry registry = new SchemeRegistry();
		registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
		registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
		ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(params, registry);

		DefaultHttpClient defaultHttpClient = new DefaultHttpClient(connectionManager, params);
		defaultHttpClient.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(0, false));
		defaultHttpClient
			.setRoutePlanner(new ProxySelectorRoutePlanner(registry, ProxySelector.getDefault()));


		ConnectionKeepAliveStrategy connectionKeepAliveStrategy = new ConnectionKeepAliveStrategy() {
			@Override
			public long getKeepAliveDuration(org.apache.http.HttpResponse httpResponse,
											 HttpContext httpContext) {
				return 20 * 1000; // 20 seconds,because tomcat default keep-alive timeout is 20s
			}
		};
		defaultHttpClient.setKeepAliveStrategy(connectionKeepAliveStrategy);

		httpTransport = new ApacheHttpTransport(defaultHttpClient);

		requestFactory = httpTransport.createRequestFactory();

	}

	public static void main(String[] args) {
		String url = "http://fy.webxml.com.cn/webservices/EnglishChinese.asmx?wsdl";
		String soapXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\"><soap12:Body><TranslatorString xmlns=\"http://WebXml.com.cn/\"><wordKey>test</wordKey></TranslatorString></soap12:Body></soap12:Envelope>";
		PostParam postParam = new PostParam(url, soapXml, true);
		System.out.println(postWithJson(postParam));
		System.out.println(testWsdlConnection(url));
		System.out.println(testWsdlConnection("http://10.242.0.51/data-transfer/ws/RoadTransService?wsdl"));
	}

	public static boolean testWsdlConnection(String address) {
		boolean flag = false;
		try {
			URL urlObj = new URL(address);
			HttpURLConnection oc = (HttpURLConnection) urlObj.openConnection();
			oc.setUseCaches(false);
			oc.setConnectTimeout(3000);    //设置超时时间
			int status = oc.getResponseCode();//请求状态
			if (200 == status) {
				return true;
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
			log.error("请求地址不通。。GjcbdwxxUtil。" + address);
		} catch (IOException e) {
			e.printStackTrace();
			log.error("请求地址不通。。GjcbdwxxUtil。" + address);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("请求地址不通。。GjcbdwxxUtil。" + address);
		}
		return flag;
	}

	@Data
	public static class PostParam {

		private Integer connectTimeoutMills;  // 可选,默认 20s
		private Integer readTimeoutMills;  // 可选，默认 20s
		private Map<String, String> headers; // 可选
		private String url; //必填
		private String postJson; //必填
		private Boolean readResponseData; //必填：是否需要读取数据。如果不需要返回结果,设置 false
		private BackOff backOff; //可选,重试机制策略
		private String authorization; //可选


		public PostParam(String url, String postJson){
			this(url, postJson, true);
		}

		public PostParam(String url, String postJson, boolean readResponseData) {
			this.url = url;
			this.postJson = postJson;
			this.readResponseData = readResponseData;
		}
	}

	public static String postWithJson(PostParam postParam) {
		GenericUrl genericUrl = new GenericUrl(postParam.getUrl());
		HttpContent httpContent = ByteArrayContent.fromString(null, postParam.getPostJson());
		HttpResponse httpResponse = null;
		try {
			HttpRequest httpRequest = requestFactory.buildPostRequest(genericUrl, httpContent);
			if (postParam.getConnectTimeoutMills() != null) {
				httpRequest.setConnectTimeout(postParam.getConnectTimeoutMills());
			}
			if (postParam.getReadTimeoutMills() != null) {
				httpRequest.setReadTimeout(postParam.getReadTimeoutMills());
			}

			HttpHeaders httpHeaders = new HttpHeaders();
			httpHeaders.setContentType(CONTENT_TYPE_JSON);

			httpRequest.setHeaders(httpHeaders);
			httpResponse = httpRequest.execute();
			if (httpResponse.getStatusCode() != HttpStatusCodes.STATUS_CODE_OK) {
				log.error("http status not 200. param:{},status:{},msg:{}", postParam,
					httpResponse.getStatusCode(), httpResponse.getStatusMessage());
				return null;
			}
			Boolean readResponseData = postParam.getReadResponseData();
			if (readResponseData != null && readResponseData) {
				InputStream inputStream = httpResponse.getContent();
				/*if (inputStream != null) {
					StringBuffer out = new StringBuffer();
					byte[] b = new byte[CACHE_SIZE];
					for (int n; (n = inputStream.read(b)) != -1; ) {
						out.append(new String(b, 0, n));
					}
					return out.toString();
				}*/
				List<String> strings = IOUtils.readLines(inputStream, "UTF-8");
				String collect = strings.stream().collect(Collectors.joining(""));
				log.info("HttpClientUtils ===>> result : {}", collect);
				return collect;
			}
		} catch (Exception e) {
			log.error("post exception,param:{}", postParam, e);
			return null;
		} finally {
			try {
				if (httpResponse != null) {
					httpResponse.disconnect();
				}
			} catch (Exception e) {
				log.error("httpResponse disconnect exception", e);
			}
		}
		return null;
	}

	@PreDestroy
	public static void destory() {
		try {
			log.info("httpTransport shutdown now....");
			httpTransport.shutdown();
		} catch (IOException e) {
			log.error("shut down httpTransport exception", e);
		}
	}
}
